package com.gitee.wsl.collections.iterator.api


typealias MutableMapEntry<K, V> = MutableMap.MutableEntry<K, V>

typealias MutableMapEntryIterator<K, V> = MutableIterator<MutableMapEntry<K, V>>


/**
 * Defines an iterator that operates over a `Map`.
 *
 *
 * This iterator is a special version designed for maps. It can be more
 * efficient to use this rather than an entry set iterator where the option
 * is available, and it is certainly more convenient.
 *
 *
 *
 * A map that provides this interface may not hold the data internally using
 * Map Entry objects, thus this interface can avoid lots of object creation.
 *
 *
 *
 * In use, this iterator iterates through the keys in the map. After each call
 * to `next()`, the `getValue()` method provides direct
 * access to the value. The value can also be set using `setValue()`.
 *
 * <pre>`MapIterator<String,Integer> it = map.mapIterator();
 * while (it.hasNext()) {
 * String key = it.next();
 * Integer value = it.getValue();
 * it.setValue(value + 1);
 * }
`</pre> *
 *
 * @param <K> the type of the keys in the map
 * @param <V> the type of the values in the map
 * @since 3.0
</V></K> */
interface MapIterator<K, V> : Iterator<K> {

    /**
     * Gets the current key, which is the key returned by the last call
     * to `next()`.
     *
     * @return the current key
     * @throws IllegalStateException if `next()` has not yet been called
     */
    fun getKey(): K

    /**
     * Gets the current value, which is the value associated with the last key
     * returned by `next()`.
     *
     * @return the current value
     * @throws IllegalStateException if `next()` has not yet been called
     */
    fun getValue(): V


    /**
     * Checks to see if there are more entries still to be iterated.
     *
     * @return `true` if the iterator has more elements
     */
    override fun hasNext(): Boolean

    /**
     * Gets the next *key* from the `Map`.
     *
     * @return the next key in the iteration
     * @throws NoSuchElementException if the iteration is finished
     */
    override fun next(): K

}

interface MutableMapIterator<K, V> :MapIterator<K, V>, MutableIterator<K> {
    /**
     * Sets the value associated with the current key (optional operation).
     *
     * @param value  the new value
     * @return the previous value
     * @throws UnsupportedOperationException if setValue is not supported by the map
     * @throws IllegalStateException if `next()` has not yet been called
     * @throws IllegalStateException if `remove()` has been called since the
     * last call to `next()`
     */
    fun setValue(value: V): V

    /**
     * Removes the last returned key from the underlying `Map` (optional operation).
     *
     *
     * This method can be called once per call to `next()`.
     *
     *
     * @throws UnsupportedOperationException if remove is not supported by the map
     * @throws IllegalStateException if `next()` has not yet been called
     * @throws IllegalStateException if `remove()` has already been called
     * since the last call to `next()`
     */
     override fun remove()
}

object EmptyMapIterator:MapIterator<Nothing, Nothing>{
    override fun getKey(): Nothing= throw NoSuchElementException("Empty iterator")

    override fun getValue(): Nothing = throw NoSuchElementException("Empty iterator")

    override fun hasNext(): Boolean = false

    override fun next(): Nothing = throw NoSuchElementException("Empty iterator")
}

object EmptyMapMutableIterator:MutableMapIterator<Nothing, Nothing>{
    override fun getKey(): Nothing= throw NoSuchElementException("Empty iterator")

    override fun getValue(): Nothing = throw NoSuchElementException("Empty iterator")

    override fun hasNext(): Boolean = false

    override fun next(): Nothing = throw NoSuchElementException("Empty iterator")
    override fun setValue(value: Nothing): Nothing = throw NoSuchElementException("Empty iterator")

    override fun remove() {

    }
}